home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1994-09-22 | 16.4 KB | 401 lines |
- IMPLEMENTATION MODULE MEMORY;
-
- (*****************************************************************************)
- (* Da das Programmieren dieser hardwarenahen Funktionen in MODULA zu vielen *)
- (* unschoenen Verrenkungen gefuehrt haette, wurden sie gleich alle in ASSEM- *)
- (* BLER programmiert. *)
- (* *)
- (* Allgemeine Vorgehensweise: *)
- (* ------------------------------------------------------------------------- *)
- (* Sind die Startadressen der Speicherbereiche ungerade, wird ein Byte vorne-*)
- (* weg geschrieben und die Anzahl um eins verringert; danach wird die Anzahl *)
- (* der Bytes in die Anzahl der entsprechenden Langworte umgerechnet, damit *)
- (* das Kopieren moeglichst schnell geht. Aus einer ungeraden Startadresse *)
- (* und/oder einer ungeraden Anzahl kann es sich ergeben, dass zum Schluss *)
- (* ein einzelnes Wort und/oder Byte geschrieben werden muessen. *)
- (* *)
- (* Beim Kopieren von Speicherbereichen muss noch darauf geachtet werden, dass*)
- (* mit dem ENDE des Speicherbereichs begonnen wird, falls der Zielbereich *)
- (* ueberlappend HINTER dem Quellbereich liegt; liegt der Zielbereich hinge- *)
- (* gen ueberlappend VOR dem Quellbereich, muss mit dem ANFANG des Quellbe- *)
- (* reichs begonnen werden. ( Haelt man sich nicht an diese Regeln, wird der *)
- (* Quellbereich waehrend des Kopierens ueberschrieben ). *)
- (*___________________________________________________________________________*)
- (* *)
- (* Oktober '89 *)
- (* Beginn auf dem Papier *)
- (* 23-Nov-89 , hk *)
- (* erste Version *)
- (* 31-Dez-89 , hk *)
- (* "CopySmallMem" fuer kleine Speicherbereiche *)
- (* 07-Feb-90 , hk *)
- (* Typ "CopyProc" *)
- (*****************************************************************************)
-
- FROM SYSTEM IMPORT (* TYPE *) ADDRESS,
- (* PROC *) INLINE;
-
- (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
-
-
- PROCEDURE ClearMem ((* EIN/ -- *) start : ADDRESS;
- (* EIN/ -- *) laenge : CARDINAL );
- (*T*)
- BEGIN
- (*
- laenge EQU 12
- start EQU laenge + 2
-
- ClearMem:
- move.w laenge(a6), d0 ; Anzahl zu loeschender Bytes
- beq.s ende ; B: nichts zu loeschen
- movea.l start(a6), a0 ; a0 -> Startadresse
- move.l a0, d2 ; fuer Bittest noetig
- moveq #0, d1 ; statt clr.X fuer schnelles Loeschen
- btst #0, d2 ; Startadresse ungerade ?
- beq.s wordcnt ; B: nein
- move.b d1, (a0)+ ; sonst das erste Byte loeschen -> gerade Adr.
- subq.w #1, d0 ; ein Byte weniger zu loeschen
- wordcnt:
- move.w d0, d2 ; Anzahl fuer spaeteren Ueberhangtest
- lsr.w #2, d0 ; Anzahl zu loeschender Langworte
- bra.s clrlp + 2 ; langwortweise loeschen
- clrlp: ;
- move.l d1, (a0)+ ;
- dbra d0, clrlp ;
- btst #1, d2 ; erst auf zusaetzliches Wort statt Byte testen,
- ; damit gerade Adresse
- beq.s tstbyte ; B: kein zusaetzliches Wort
- move.w d1, (a0)+ ; ein Wort loeschen
- tstbyte:
- btst #0, d2 ; noch ein letztes Byte ?
- beq.s ende ; B: nein
- move.b d1, (a0) ; der letzte Rest, jetzt ist ung. Adr., egal
- ende:
- *)
- INLINE( 302EH,000CH,672EH,206EH,000EH,2408H,7200H,0802H,0000H );
- INLINE( 6704H,10C1H,5340H,3400H,0E448H,6002H,20C1H,51C8H,0FFFCH );
- INLINE( 0802H,0001H,6702H,30C1H,0802H,0000H,6702H,1081H );
-
- END ClearMem;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE FillMem ((* EIN/ -- *) start : ADDRESS;
- (* EIN/ -- *) laenge : CARDINAL;
- (* EIN/ -- *) muster : LONGCARD );
- (*T*)
- BEGIN
- (*
- muster EQU 12
- laenge EQU muster + 4
- start EQU laenge + 2
-
- FillMem:
- move.w laenge(a6), d0 ; Anzahl zu fuellender Bytes
- beq.s ende ; B: nix los
- movea.l start(a6), a0 ; a0 -> Startadresse
- move.l a0, d2 ; fuer Bittest noetig
- move.l muster(a6), d1 ; Fuellmuster
- btst #0, d2 ; ungerade Startadr. ?
- beq.s wordcnt ; B: nein
- rol.l #8, d1 ; es soll ja mit dem hoechstwertigen Byte des
- ; des Musters begonnen werden, damit gibt es
- ; auch ein kontinuierliches Muster beginnend
- ; mit einer ungeraden Adr. ( die drei folgenden
- ; Bytes ruecken bei dem ROTATE-Befehl entsprechend
- ; auf, und das erste Byte folgt wieder dahinter
- move.b d1, (a0)+ ;
- subq.w #1, d0 ; ein Byte weniger zu fuellen
- wordcnt:
- move.w d0, d2 ; fuer spaeteren Ueberhangtest
- lsr.w #2, d0 ; Anzahl zu fuellender Langworte
- bra.s fillp + 2 ; Speicherbereich langwortweise beschreiben
- fillp:
- move.l d1, (a0)+ ;
- dbra d0, fillp ;
- btst #1, d2 ; noch ein zusaetzliches Wort ?
- beq.s tstbyte ; B: nein
- swap d1 ; damit werden zwei Byte des Musters von links
- move.w d1, (a0)+ ; zusaetzlich geschrieben
- tstbyte:
- btst #0, d2 ; noch ein zusaetzliches Byte ?
- beq.s ende ; B: nein
- rol.l #8, d1 ; damit ist das auf das letzte bisher geschriebene
- ; Byte des Musters folgende im unteren Byte des
- ; Registers
- move.b d1, (a0) ;
- ende:
- *)
- INLINE( 302EH,0010H,6736H,206EH,0012H,2408H,222EH,000CH,0802H );
- INLINE( 0000H,6706H,0E199H,10C1H,5340H,3400H,0E448H,6002H,20C1H );
- INLINE( 51C8H,0FFFCH,0802H,0001H,6704H,4841H,30C1H,0802H,0000H );
- INLINE( 6704H,0E199H,1081H );
-
- END FillMem;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE CopyMem ((* EIN/ -- *) quelle,
- (* EIN/ -- *) ziel : ADDRESS;
- (* EIN/ -- *) laenge : CARDINAL );
- (*T*)
- BEGIN
- (*
- laenge EQU 12
- ziel EQU laenge + 2
- quelle EQU ziel + 4
-
- CopyMem:
- move.w laenge(a6),d0 ; Anzahl der Bytes
- beq ende ; nix zu kopieren
- movea.l quelle(a6),a0 ; a0 -> quelle
- movea.l ziel(a6),a1 ; a1 -> ziel
- cmpa.l a0, a1 ; Quelle vor Ziel ?
- shi d3 ; B: ja merken ( d3 # 0 <=> von hinten mit
- ; Predekrement -(ax) kopieren )
- bls.s tstalgn ; B: nein, kann mit Postinkr. kopiert werden
- adda.w d0,a0 ; sonst von hinten mit Predekr. kopieren
- adda.w d0,a1 ; a0, a1 -> eins hinter letztem Byte
- tstalgn:
- move.l a0,d1
- move.l a1,d2
- eor.b d2,d1 ; genau eine Adr. ungerade ?
- btst #0,d1 ;
- beq.s fastcp ; B: nein, beide gerade/ungerade -> schnell kop.
- tst.b d3 ; welche Richtung kopieren ?
- bne.s slspcp+2 ; B: von hinten
- bra.s slnrmcp+2 ; B: sonst von vorne
- slnrmcp:
- move.b (a0)+,(a1)+
- dbra d0,slnrmcp
- bra ende ; fertig
-
- slspcp:
- move.b -(a0),-(a1) ; alles byteweise von hinten nach vorne kopieren
- dbra d0,slspcp ;
- bra ende ; fertig
-
- fastcp:
- btst #0,d2 ; beide Adr. gerade oder beide ungerade ?
- beq.s longcnt ; B: beide gerade, kein Byte vorneweg
- tst.b d3 ; welche Richtung ?
- bne.s snglsp ; B: von hinten
- move.b (a0)+,(a1)+ ; ein Byte -> gerade Adresse
- bra.s decone
- snglsp:
- move.b -(a0),-(a1) ; ein Byte -> gerade Adresse
- decone:
- subq.w #1,d0 ; ein Byte weniger zu kopieren
- longcnt:
- move.w d0,d2 ; fuer spaeteren Ueberhangtest
- lsr.w #2,d0 ; Anzahl zu kopierender Langworte
- tst.b d3 ; welche Richtung ?
- bne.s copysp+2 ; B: von hinten alles langwortweise kopieren
- bra.s copynrm+2 ; B: von vorne
- copynrm:
- move.l (a0)+,(a1)+
- dbra d0,copynrm
- btst #1,d2 ; ein zusaetzliches Wort ?
- beq.s tstbtnrm ; B: nein
- move.w (a0)+,(a1)+ ; ein Wort zusaetzlich
- tstbtnrm:
- btst #0,d2 ; ein zusaetzliches Byte ?
- beq.s ende ; B: nein, fertig
- move.b (a0)+,(a1)+ ;
- bra.s ende ; fertig
-
- copysp:
- move.l -(a0),-(a1) ; Schleife und Abfragen wie oben
- dbra d0,copysp
- btst #1,d2
- beq.s tstbtsp
- move.w -(a0),-(a1)
- tstbtsp:
- btst #0,d2
- beq.s ende
- move.b -(a0),-(a1)
- ende:
- *)
- INLINE( 302EH,000CH,6700H,0084H,206EH,0012H,226EH,000EH,0B3C8H );
- INLINE( 52C3H,6304H,0D0C0H,0D2C0H,2208H,2409H,0B501H,0801H,0000H );
- INLINE( 671AH,4A03H,660EH,6002H,12D8H,51C8H,0FFFCH,6000H,0056H );
- INLINE( 1320H,51C8H,0FFFCH,6000H,004CH,0802H,0000H,670CH,4A03H );
- INLINE( 6604H,12D8H,6002H,1320H,5340H,3400H,0E448H,4A03H,661CH );
- INLINE( 6002H,22D8H,51C8H,0FFFCH,0802H,0001H,6702H,32D8H,0802H );
- INLINE( 0000H,671AH,12D8H,6016H,2320H,51C8H,0FFFCH,0802H,0001H );
- INLINE( 6702H,3320H,0802H,0000H,6702H,1320H );
-
- END CopyMem;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE CopySmallMem ((* EIN/ -- *) quelle,
- (* EIN/ -- *) ziel : ADDRESS;
- (* EIN/ -- *) laenge : CARDINAL );
- (*T*)
- BEGIN
- (*
- laenge EQU 12
- ziel EQU laenge + 2
- quelle EQU ziel + 4
-
- CopySmallMem:
- move.w laenge(a6),d0 ; Anzahl der Bytes
- movea.l quelle(a6),a0 ; a0 -> quelle
- movea.l ziel(a6),a1 ; a1 -> ziel
- bra.s cpylp + 2 ; byteweise kopieren,ohne Ruecksicht auf Verluste
- cpylp:
- move.b (a0)+, (a1)+
- dbra d0, cpylp
- *)
- INLINE( 302EH,000CH,206EH,0012H,226EH,000EH,6002H,12D8H,51C8H,0FFFCH );
-
- END CopySmallMem;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE SwapMem ((* EIN/ -- *) block1,
- (* EIN/ -- *) block2 : ADDRESS;
- (* EIN/ -- *) laenge : CARDINAL );
- (*T*)
- BEGIN
- (*
- anzahl EQU 12
- block2 EQU anzahl + 2
- block1 EQU block2 + 4
-
- SwapMem:
- move.w anzahl(a6), d0 ; Anzahl zu tauschender Bytes
- beq.s ende ; B: nichts zu vertauschen
- movea.l block1(a6), a0
- movea.l block2(a6), a1
- tstslow:
- move.l a0, d1
- move.l a1, d2
- eor.b d2, d1 ; genau eine der Adressen ungerade ?
- btst #0, d1 ;
- beq.s fastswap ; B: nein
- bra.s slowswap + 6 ; sonst die beiden Bloecke byteweise vertauschen
- slowswap:
- move.b (a0), d1
- move.b (a1), (a0)+
- move.b d1, (a1)+
- dbra d0, slowswap
- bra.s ende ; fertig
-
- fastswap:
- btst #0, d2 ; beide Adr. ungerade oder beide gerade ?
- beq.s longcnt ; B: beide gerade
- move.b (a0), d1 ; sonst ein Byte vorneweg tauschen
- move.b (a1), (a0)+ ; -> gerade Adresse
- move.b d1, (a1)+
- subq.w #1, d0 ; eins weniger zu tauschen
- longcnt:
- move.w d0, d2 ; fuer spaeteren Ueberhangtest
- lsr.w #2, d0 ; Anzahl auszutauschender Langworte
- bra.s swaplp + 6 ; die Bloecke langwortweise vertauschen
- swaplp:
- move.l (a0), d1
- move.l (a1), (a0)+
- move.l d1, (a1)+
- dbra d0, swaplp
- btst #1, d2 ; noch ein zusaetzl. Wort auszutauschen ?
- beq.s tstbtswap ; B: nein
- move.w (a0), d1
- move.w (a1), (a0)+
- move.w d1, (a1)+
- tstbtswap:
- btst #0, d2 ; noch ein Byte ?
- beq.s ende ; B: nein, fertig
- move.b (a0), d1
- move.b (a1), (a0)
- move.b d1, (a1)
- ende:
- *)
- INLINE( 302EH,000CH,6758H,206EH,0012H,226EH,000EH );
- INLINE( 2208H,2409H,0B501H,0801H,0000H,670EH,6006H,1210H );
- INLINE( 10D1H,12C1H,51C8H,0FFF8H,6036H,0802H,0000H,6708H,1210H );
- INLINE( 10D1H,12C1H,5340H,3400H,0E448H,6006H,2210H,20D1H,22C1H );
- INLINE( 51C8H,0FFF8H,0802H,0001H,6706H,3210H,30D1H,32C1H,0802H );
- INLINE( 0000H,6706H,1210H,1091H,1281H );
-
- END SwapMem;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE EqualMem ((* EIN/ -- *) block1,
- (* EIN/ -- *) block2 : ADDRESS;
- (* EIN/ -- *) laenge : CARDINAL ): BOOLEAN;
- (*T*)
- BEGIN
- (*
- anzahl EQU 12
- block2 EQU anzahl + 2
- block1 EQU block2 + 4
- RETURN EQU block1 + 4
-
- EqualMem:
- move.w anzahl(a6), d0 ; Anzahl zu vergl. Bytes
- beq.s equal ; B: nichts zu vergleichen
- movea.l block1(a6), a0 ; a0 -> block1
- movea.l block2(a6), a1 ; a1 -> block2
- moveq #0, d3 ; Default: FALSE
- move.l a0, d1 ; fuer Bittest
- move.l a1, d2 ;
- eor.b d2, d1 ; genau eine Adr. ungerade ?
- btst #0, d1 ;
- beq.s fastcmp ; B: nein, beide gerade/ungerade
- moveq #0, d7 ; damit beim ersten DBNE-Befehl die Bedingung
- ; NE nicht erfuellt ist, sonst wird die Schleife
- ; nie ausgefuehrt und die beiden Speicherbereiche
- ; werden grundsaetzlich fuer ungleich gehalten !!
- bra.s slowcmp + 2 ; sonst alles byteweise vergleichen
- slowcmp:
- cmpm.b (a0)+, (a1)+
- dbne d0, slowcmp
- bne.s ende ; B: ein unterschiedliches Byte gefunden
- bra.s equal ; B: Bloecke sind gleich
-
- fastcmp:
- btst #0, d2 ; beide Adressen ungerade ?
- beq.s calclw ; B: nein, beide gerade
- cmpm.b (a0)+, (a1)+ ; sonst ein Byte vergl. -> gerade Adr.
- bne.s ende ; B: schon das erste Byte unterschiedlich
- subq.w #1, d0 ; sonst ein Byte weniger zu vergleichen
- calclw:
- move.w d0, d2 ; fuer Ueberhangtest
- lsr.w #2, d0 ; Anzahl zu vergleichender Langworte
- moveq #0, d7 ; damit beim ersten DBNE-Befehl die Bedingung
- ; NE nicht erfuellt ist
- bra.s longcmp + 2 ; alles langwortweise vergleichen
- longcmp:
- cmpm.l (a0)+, (a1)+
- dbne d0, longcmp
- bne.s ende ; B: unterschiedliches Byte entdeckt
- btst #1, d2 ; noch ein abschliessendes Wort vergl. ?
- beq.s tstbyte ; B: nein
- cmpm.w (a0)+, (a1)+ ; letztes Wort auch gleich ?
- bne.s ende ; B: nein, Bloecke nicht gleich
- tstbyte:
- btst #0, d2 ; letztes Byte vergl. ?
- beq.s equal ; B: nein, bis hierhin alles gleich
- cmpm.b (a0)+, (a1)+ ; letztes Byte auch gleich ?
- bne.s ende ; B: nein, jetzt hats uns doch noch erwischt
- equal:
- moveq #1, d3 ; sonst TRUE
- ende:
- move.b d3, RETURN(a6)
- *)
- INLINE( 302EH,000CH,6754H,206EH,0012H,226EH,000EH,7600H,2208H );
- INLINE( 2409H,0B501H,0801H,0000H,670EH,7E00H,6002H,0B308H,56C8H );
- INLINE( 0FFFCH,6634H,6030H,0802H,0000H,6706H,0B308H,6628H,5340H );
- INLINE( 3400H,0E448H,7E00H,6002H,0B388H,56C8H,0FFFCH,6616H,0802H );
- INLINE( 0001H,6704H,0B348H,660CH,0802H,0000H,6704H,0B308H,6602H );
- INLINE( 7601H,1D43H,0016H );
-
- END EqualMem;
-
-
- END MEMORY.
-